package fyp.spedmew.backend.entity;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.config.Named;
import com.google.api.server.spi.config.Nullable;
import com.google.api.server.spi.response.CollectionResponse;
import com.google.api.server.spi.response.ConflictException;
import com.google.api.server.spi.response.NotFoundException;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.datastore.QueryResultIterator;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.cmd.Query;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import fyp.spedmew.backend.category.BooleanResponse;

import static fyp.spedmew.backend.service.OfyService.ofy;

@Api(name = "jobEndpoint", version = "v1", namespace = @ApiNamespace(ownerDomain = "entity.backend.spedmew.fyp", ownerName = "entity.backend.spedmew.fyp", packagePath=""))
public class JobEndpoint {
    private static final Logger log = Logger.getLogger(JobEndpoint.class.getName());

    // Make sure to add this endpoint to your web.xml file if this is a web application.
    public JobEndpoint() {

    }

    /**
     * Return a collection of Jobs
     *
     * @param count The number of Jobs
     * @return a list of Jobs
     */
    public List<Job> listJob(@Nullable @Named("cursor") String cursorString,
                                               @Nullable @Named("count") Integer count) {
        log.info("listJob called");
        return ofy().load().type(Job.class).list();
//        if (count != null) query.limit(count);
//        if (cursorString != null && cursorString != "") {
//            query = query.startAt(Cursor.fromWebSafeString(cursorString));
//        }
//
//        List<Job> records = new ArrayList<Job>();
//        QueryResultIterator<Job> iterator = query.iterator();
//        int num = 0;
//        while (iterator.hasNext()) {
//            records.add(iterator.next());
//            if (count != null) {
//                num++;
//                if (num == count) break;
//            }
//        }
//
//        //Find the next cursor
//        if (cursorString != null && cursorString != "") {
//            Cursor cursor = iterator.getCursor();
//            if (cursor != null) {
//                cursorString = cursor.toWebSafeString();
//            }
//        }
//        return CollectionResponse.<Job>builder().setItems(records).setNextPageToken(cursorString).build();
    }

    /**
     * This inserts a new <code>Job</code> object.
     * @param job The object to be added.
     * @return The object to be added.
     */
    public Job insertJob(Job job) throws ConflictException {
        log.info("insertJob called");
        //If if is not null, then check if it exists. If yes, throw an Exception
        //that it is already present
        if (job.getId() != null) {
            if (findRecord(job.getId()) != null) {
                throw new ConflictException("Object already exists");
            }
        }
        //Since our @Id field is a Long, Objectify will generate a unique value for us
        //when we use put
        ofy().save().entity(job).now();
        return job;
    }

    /**
     * This updates an existing <code>Job</code> object.
     * @param job The object to be added.
     * @return The object to be updated.
     */
    public Job updateJob(Job job)throws NotFoundException {
        if (findRecord(job.getId()) == null) {
            throw new NotFoundException("Job record does not exist");
        }
        ofy().save().entity(job).now();
        return job;
    }

    /**
     * This updates an existing <code>Job</code> object with new status.
     * @param id The object to be added.
     * @return The object to be updated.
     */
    public BooleanResponse updateJobStatus(@Named("id") Long id, @Named("status") String status)throws NotFoundException {
        Job job = findRecord(id);
        if (job != null) {
            job.setStatus(status);
            ofy().save().entity(job).now();
            return BooleanResponse.getTrue();
        } else {
            return BooleanResponse.getFalse();
        }
    }

    /**
     * This deletes an existing <code>Job</code> object.
     * @param id The id of the object to be deleted.
     */
    public void removeJob(@Named("id") Long id) throws NotFoundException {
        Job record = findRecord(id);
        if(record == null) {
            throw new NotFoundException("Job Record does not exist");
        }
        ofy().delete().entity(record).now();
    }

    /**
     * This methods find Jobs by sender
     * @param username The id of the object to be deleted.
     */
    public List<Job> findJobBySender(@Named("username") String username) throws NotFoundException {
        User user = ofy().load().type(User.class).filter("name", username.toLowerCase()).first().now();
        return ofy().load().type(Job.class).filter("sender", user).list();
    }

    /**
     * This method to retrieve a <code>Job</code> record
     */
    public Job findRecord(@Named("id") Long id) {
        return ofy().load().type(Job.class).id(id).now();
    }
}